﻿using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using T.FAS.Runtime.Base.Entity;

namespace T.FAS.Runtime.Metadata.Entity.DataModel
{
    /// <summary>
    /// 数据对象
    /// </summary>
    [Serializable]
    public partial class DataObject : AbsMetaDataContent
    {
        /// <summary>
        /// ID
        /// </summary>
        public string ID { get; set; }
        /// <summary>
        /// 标识
        /// </summary>
        public string Code { get; set; }
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 描述
        /// </summary>
        public string Descriptions { get; set; }
        /// <summary>
        /// 数据源名称
        /// </summary>
        public string DataSourceName { get; set; }
        /// <summary>
        /// 表名称
        /// </summary>
        public string LogicTableName { get; set; }
        /// <summary>
        /// 物理表名集合，以逗号间隔
        /// </summary>
        public string ActualTableNames { get; set; }
        /// <summary>
        /// 是否表分区
        /// </summary>
        [JsonIgnore]
        public bool IsTableSharding { get; set; }
        /// <summary>
        /// 表分区策略ID
        /// </summary>
        [JsonIgnore]
        public string TableShardingStrategyID { get; set; }
        /// <summary>
        /// 是否分库
        /// </summary>
        [JsonIgnore]
        public bool IsDatabaseSharding { get; set; }
        /// <summary>
        /// 是否视图
        /// </summary>
        public bool IsView { get; set; }
        /// <summary>
        /// 是否逻辑删除
        /// </summary>
        [JsonIgnore]
        public bool IsLogicallyDeleted { get; set; }
        /// <summary>
        /// 版本
        /// </summary>
        [JsonIgnore]
        public int Version { get; set; }
        /// <summary>
        /// 备用字段
        /// </summary>
        [JsonIgnore]
        public string Ext1 { get; set; }
        /// <summary>
        /// 备用字段
        /// </summary>
        [JsonIgnore]
        public string Ext2 { get; set; }
        /// <summary>
        /// 备用字段
        /// </summary>
        [JsonIgnore]
        public string Ext3 { get; set; }
        /// <summary>
        /// 创建人
        /// </summary>
        public override string Creator { get; set; }
        /// <summary>
        /// 创建时间
        /// </summary>        
        public override DateTime CreateTime { get; set; }
        /// <summary>
        /// 最后修改人
        /// </summary>
        public override string LastModifier { get; set; }
        /// <summary>
        /// 最后修改时间
        /// </summary>        
        public override DateTime LastModifyTime { get; set; }
        private List<DataColumn> columns;
        /// <summary>
        /// 列集合
        /// </summary>
        public List<DataColumn> Columns
        {
            get
            {
                if (columns == null)
                    columns = new List<DataColumn>();

                return columns;
            }
            set
            {
                columns = value;
            }
        }
        /// <summary>
        /// 主键列集合，去掉JsonIgnore标记，会影响CDO运行时获取主键列的结果
        /// </summary>
        [JsonProperty(ReferenceLoopHandling = ReferenceLoopHandling.Ignore)]
        public List<DataColumn> PKColumns
        {
            get
            {
                return Columns.Where(i => i.IsPkColumn).ToList();
            }
        }
        /// <summary>
        /// 分区列
        /// </summary>
        /// 
        [JsonIgnore]
        [JsonProperty(ReferenceLoopHandling = ReferenceLoopHandling.Ignore)]
        public DataColumn ShardingColumn
        {
            get
            {
                return Columns.FirstOrDefault(i => i.IsShardingColumn);
            }
        }

        ///// <summary>
        ///// 是否缓存
        ///// </summary>
        //public bool IsCache { get; set; }

        ///// <summary>
        ///// 缓存策略
        ///// </summary>
        //public string CacheStrategy { get; set; }

        /*******************FAS低代码平台新增字段*******************/
        /// <summary>
        /// 是否SDO，true: SDO， false: DO
        /// </summary>
        public bool IsStatic { get; set; }
        /// <summary>
        /// 数据库id
        /// </summary>
        public string DatabaseID { get; set; }
        public Database Database { get; set; }
        /// <summary>
        /// 当前访问数据库的配置key，默认值为数据库Database的默认配置
        /// </summary>
        public string CurrentConfigKey { get; set; }
        /// <summary>
        /// 是否主数据DO
        /// </summary>
        public bool IsMainData { get; set; }
        /// <summary>
        /// 是否引用DO
        /// </summary>
        public bool IsReference { get; set; }
        /// <summary>
        /// 引用DO.id
        /// </summary>
        public string RefDataObjectID { get; set; }
        /// <summary>
        /// 来源的元数据ID，例如DA（数据资产对象）
        /// </summary>
        public string RelatedMetaDataID { get; set; }
        /// <summary>
        /// 租户id
        /// </summary>
        public string TenantID { get; set; }
        /// <summary>
        /// 是否同步生成DDL语句，true:不生成 false:生成
        /// </summary>
        public bool DisableSyncStructure { get; set; }
        /// <summary>
        /// 项目可见性 0:项目内可见 1:所有人可见
        /// </summary>
        public int Visibility { get; set; }
        /// <summary>
        /// 启用全量更新  0:否，1:是
        /// </summary>
        public bool EnableFulldoseUpdate { get; set; }
        /// <summary>
        /// 启用事件   0:否，1:是
        /// </summary>
        public bool EnableEvent { get; set; }
        /// <summary>
        /// 启用全部审计日志  0:否，1:是
        /// </summary>
        public bool EnableAuditLog { get; set; }
        /// <summary>
        /// 启用逻辑删除  0:否，1:是
        /// </summary>
        public bool EnableLogicalDelete { get; set; }
        /// <summary>
        /// 启用类型精确控制  0:否，1:是
        /// </summary>
        public bool EnableAccuracyControl { get; set; }
        #region ***************************辅助语言映射***************************
        /// <summary>
        /// 辅助语言与表I18N字段后缀映射
        /// </summary>
        public string ParalanguageTableI18NFieldSuffixMappingContent { get; set; }
        [JsonIgnore]
        private Dictionary<string, string> _paralanguageTableI18NFieldSuffixMapping;
        /// <summary>
        /// 辅助语言与表I18N字段后缀映射字典
        /// </summary>
        [JsonIgnore]
        public Dictionary<string, string> ParalanguageTableI18NFieldSuffixMapping
        {
            get
            {
                if (_paralanguageTableI18NFieldSuffixMapping == null)
                {
                    if (!string.IsNullOrEmpty(ParalanguageTableI18NFieldSuffixMappingContent))
                    {
                        _paralanguageTableI18NFieldSuffixMapping = new Dictionary<string, string>();
                        try
                        {
                            List<KeyValuePair<string, string>> result = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(ParalanguageTableI18NFieldSuffixMappingContent)
                                                                                          .SelectMany(d => d.ToList())
                                                                                          .ToList();
                            result.ForEach(pair => _paralanguageTableI18NFieldSuffixMapping[pair.Key] = pair.Value);
                        }
                        catch
                        { 
                        }
                    }
                }
                return _paralanguageTableI18NFieldSuffixMapping;
            }
        }
        #endregion
        #region ***************************子表属性***************************
        /// <summary>
        /// 数据对象列关联关系，是数据对象的一部分，关联DataObjectRelation.ToDoID
        /// </summary>
        public List<DataObjectRelation> DataObjectRelations { get; set; } = new List<DataObjectRelation>();
        /// <summary>
        /// 数据对象索引
        /// </summary>
        public List<DataObjectIndex> DataObjectIndexs { get; set; } = new List<DataObjectIndex>();
        /// <summary>
        /// 统一字段帮助
        /// </summary>
        public List<DataObjectColumnHelpSetting> ColumnHelpSettings { get; set; } = new List<DataObjectColumnHelpSetting>();
        /// <summary>
        /// 静态数据对象的预置数据，跟SDO一一对应
        /// </summary>
        public StaticDataObjectPresetData PresetData { get; set; } = new StaticDataObjectPresetData();
        #endregion
        #region ***************************字段分类***************************
        /// <summary>
        /// DO列分类信息-从DB获取
        /// </summary>
        public List<DataColumnCategoryInfo> ColumnCategoryInfos { get; set; } = new List<DataColumnCategoryInfo>();
        private List<DataColumnCategoryInfo> _topColumnCategoryInfos = null;
        /// <summary>
        /// DO列分类信息
        /// </summary>
        [JsonIgnore]
        public List<DataColumnCategoryInfo> TopColumnCategoryInfos
        {
            get
            {
                if (_topColumnCategoryInfos == null)
                {
                    GetCategoryTree();
                    _topColumnCategoryInfos = ColumnCategoryInfos?.Where(c => c.ParentID == "0").ToList();
                }
                return _topColumnCategoryInfos;
            }
        }
        private Dictionary<DataColumnCategoryInfo, List<DataColumn>> _columnCategoryGroupMapping = null;
        /// <summary>
        /// 获取DO字段分类=>分类下列集合的映射关系，如果都没有设置。返回默认分类=>DO所有列
        /// </summary>
        [JsonIgnore]
        public Dictionary<DataColumnCategoryInfo, List<DataColumn>> ColumnCategoryGroupMapping
        {
            get
            {
                if (_columnCategoryGroupMapping == null)
                {
                    _columnCategoryGroupMapping = new Dictionary<DataColumnCategoryInfo, List<DataColumn>>();
                    if (ColumnCategoryInfos == null)
                        _columnCategoryGroupMapping[DataColumnCategoryInfo.Default] = Columns;
                    else
                    {
                        var leafCategory = ColumnCategoryInfos.Where(c => c.ParentID != "0" && !c.IsDefault);
                        foreach (var cate in leafCategory)
                        {
                            var cateColumns = Columns.Where(col => col.CategoryInfoID == cate.ID)?.ToList();
                            if (cateColumns != null && cateColumns.Count > 0)
                            {
                                _columnCategoryGroupMapping[cate] = cateColumns;
                            }
                        }
                        //单独处理默认分类，默认只有一个默认分类
                        DataColumnCategoryInfo defaultCate = ColumnCategoryInfos.FirstOrDefault(c => c.IsDefault);
                        IEnumerable<DataColumn> hasCateColumns = null;
                        if (_columnCategoryGroupMapping != null && _columnCategoryGroupMapping.Keys.Count > 0)
                        {
                            //已经被分组的列
                            hasCateColumns = _columnCategoryGroupMapping.Values.ToList().SelectMany(colList => colList);
                        }
                        if (hasCateColumns != null && hasCateColumns.Count() > 0)
                        {
                            _columnCategoryGroupMapping[defaultCate] = Columns.Except(hasCateColumns)?.ToList();
                        }
                        else
                        {
                            _columnCategoryGroupMapping[defaultCate] = Columns;
                        }
                    }
                }
                return _columnCategoryGroupMapping;
            }
        }
        #endregion
        #region SDO预置词条发布
        /// <summary>
        /// 翻译好的词条内容，仅发布用的字段
        /// </summary>
        public Dictionary<string, List<Dictionary<string, string>>> TranslatedTerms { get; set; }

        #endregion
        #region 分区设置
        /// <summary>
        /// 分区设置（暂时用Json内容存储，后续需要拆表）
        /// </summary>
        public string ShardingSettingContent { get; set; }
        public List<ColumnShardingStrategy> _shardingSetting = null;
        public List<ColumnShardingStrategy> ShardingSetting
        {
            get
            {
                if (_shardingSetting == null)
                {
                    if (!string.IsNullOrEmpty(ShardingSettingContent))
                    {
                        _shardingSetting = new List<ColumnShardingStrategy>();
                        try
                        {
                            _shardingSetting = JsonConvert.DeserializeObject<List<ColumnShardingStrategy>>(ShardingSettingContent);
                        }
                        catch
                        {
                        }
                    }
                }
                return _shardingSetting;
            }
        }
        #endregion

        public override object Clone()
        {
            var newObject = this.MemberwiseClone() as DataObject;

            if (DataObjectRelations != null)
            {
                newObject.DataObjectRelations = new List<DataObjectRelation>();
                this.DataObjectRelations.ForEach(i => newObject.DataObjectRelations.Add(i.Clone() as DataObjectRelation));
            }

            if (Columns != null)
            {
                newObject.Columns = new List<DataColumn>();
                this.Columns.ForEach(i => newObject.Columns.Add(i.Clone() as DataColumn));
            }

            if (Columns != null)
            {
                newObject.DataObjectIndexs = new List<DataObjectIndex>();
                this.DataObjectIndexs.ForEach(i => newObject.DataObjectIndexs.Add(i.Clone() as DataObjectIndex));
            }
            
            return newObject;
        }
        /// <summary>
        /// 获取SDO的Name列
        /// </summary>
        /// <returns></returns>
        internal DataColumn GetSDONameColumn()
        {
            DataColumn pkCol = this.Columns.FirstOrDefault(col => col.IsPkColumn);
            DataColumn nameCol = default;
            //固定取Name列
            nameCol = this.Columns.FirstOrDefault(col => string.Equals(col.ColumnName, "name", StringComparison.OrdinalIgnoreCase));
            if (nameCol == null || nameCol.ApplicationDataType != DataType.String.ToString())
            {
                nameCol = this.Columns.FirstOrDefault(col => col.ColumnOrder == pkCol.ColumnOrder + 1);
                if (nameCol == null || nameCol.ApplicationDataType != DataType.String.ToString())
                {
                    nameCol = this.Columns.FirstOrDefault(col => col.ApplicationDataType == DataType.String.ToString());
                }
            }
            return nameCol;
        }
        private void GetCategoryTree()
        {
            if (ColumnCategoryInfos != null && ColumnCategoryInfos.Count > 0)
            {
                foreach (var category in ColumnCategoryInfos)
                {
                    category.Children = ColumnCategoryInfos.Where(c => c.ParentID == category.ID).ToList();
                }
            }
        }

        /// <summary>
        /// 是否启用列权限控制
        /// </summary>
        /// <returns></returns>
        public bool IsHaveColumnPermission()
        {
            if (this.Columns?.Count > 0 && this.Columns.Any(col => col.IsEnableColumnPermission))
                return true;
            return false;
        }
    }
}
